/*
  spr-sdk: Statistical Pattern Recognition SDK
  Copyright (C) 2010 Marco Ambu

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef _UTIL_UTILITY_H
#define _UTIL_UTILITY_H

#include <util/Real.h>
#include <vector>
#include <math.h>
#include <algorithm>
#include <sstream>
#include <iostream>

namespace util {

namespace Utility {

template<typename InputIterator>
InputIterator mostPresentValue(InputIterator __first, InputIterator __last, std::input_iterator_tag);

template<typename Iterator>
Iterator mostPresentValue(Iterator __first, Iterator __last)
{
  typename std::iterator_traits<Iterator>::iterator_category cat;
  return mostPresentValue(__first, __last, cat);
}


template <class Type>
Type fromString(const std::string& str);


// Implementation

template <typename Iterator>
class IteratorVectorComparer
{
public:
  bool operator()(const Iterator& a, const Iterator& b) const {
    return *a < *b;
  }
};

template<typename InputIterator>
InputIterator mostPresentValue(InputIterator __first, InputIterator __last, std::input_iterator_tag)
{
  typedef std::vector<InputIterator> IteratorVector;
  typedef typename std::vector<InputIterator>::iterator iter;
  IteratorVector sortedVector;
  for ( ; __first != __last; ++__first)
    sortedVector.push_back(__first);

  std::sort(sortedVector.begin(), sortedVector.end(), IteratorVectorComparer<InputIterator>());

  for (iter it = sortedVector.begin(); it != sortedVector.end(); ++it)
    std::cout << *(*it) << " ";
  std::cout << std::endl;

  iter mostPresent = sortedVector.begin();
  iter curr = sortedVector.begin();
  iter prev = sortedVector.begin();
  iter end = sortedVector.end();
  ++curr;
  std::size_t prevcounter = 1, currcounter = 1;
  for ( ; curr != end; )
  {
    if (*(*curr) == *(*prev))
      ++currcounter;
    bool exchange = *(*curr) != *(*prev);
    ++curr;
    exchange |= curr == end;
    if (exchange)
    {
      if (currcounter > prevcounter)
      {
        mostPresent = prev;
        prevcounter = currcounter;
      }
      currcounter = 1;
    }
    ++prev;
  }
  return *mostPresent;
}

template <class Type>
Type fromString(const std::string& str)
{
  Type t;
  std::istringstream is(str);
  is >> t;
  return t;
}

} // namespace Utility

} // namespace util

#endif // _UTIL_UTILITY_H
